package exchange

import (
	"global/core"
	"fmt"
	"time"
	"github.com/ngaut/log"
	"global/libs/structs"
	"encoding/json"
	"strings"
)

const (
	BinanceKlineResolution1min = "1m"
)

type BinanceKline struct {
	BaseKline
}

func NewBinanceKline() KlineInterface {
	return new(BinanceKline)
}

func (k *BinanceKline) Init(ctx *core.Context, slug string) error {
	k.BaseKline.init(ctx, slug)
	if err := k.loadSymbols(); err != nil {
		return err
	}
	if len(k.symbols) == 0 {
		return fmt.Errorf("init symbols failed, length 0, slug: %s", slug)
	}
	return nil
}

func (k *BinanceKline) Run() {
	fmt.Println("symbol length:", len(k.symbols))
	for _, v := range k.symbols {
		go func(symbol structs.Symbol) {
			k.startGetKline(&symbol)
		}(v)
	}
}

// 开始
func (k *BinanceKline) startGetKline(symbol *structs.Symbol)  {
	timeTicker := time.NewTicker(30 * time.Second)
	go func() {
		for t := range timeTicker.C {
			_ = t
			k.spider(symbol)
		}
	}()
}

func (k *BinanceKline) spider(symbol *structs.Symbol)  {
	symbolStr := fmt.Sprintf("%s_%s", strings.ToLower(symbol.From), strings.ToLower(symbol.To))
	datas, err := k.get(symbol)
	if err != nil {
		log.Errorf("Error: %s", err)
		return
	}
	if len(datas) == 0 { return }

	conn := k.ctx.GetBaseRedis().Get()
	defer conn.Close()

	findLastTime, err := core.GetSpiderKlineLastTime(conn, k.slug, "1min", symbolStr)
	if err != nil{
		log.Errorf("Error: error: %s, last time: %d", err, findLastTime)
		return
	}

	for i := 0; i < len(datas); i++ {
		t := time.Unix(datas[i].DateTime, 0)
		tx := t.Local().Unix()
		fx := int64(findLastTime)
		if tx < fx { continue }
		if err := core.SaveKlineDetailToSymbol(conn, "1min", *datas[i], tx != fx); err != nil {
			log.Fatalf("Error: %s", err)
			return
		}
	}
}

// 获取GET数据
func (k *BinanceKline) get(symbol *structs.Symbol) ([]*structs.SpiderKline, error) {
	url := core.GetBinanceApiV1Url("klines")
	body, err := k.BaseKline.get(url, map[string]interface{}{
		"symbol": strings.ToUpper(fmt.Sprintf("%s%s", symbol.From, symbol.To)),
		"interval": BinanceKlineResolution1min,
	})

	if err != nil {
		return nil, err
	}

	response := make([][]interface{}, 0)
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, err
	}

	datas := make([]*structs.SpiderKline, 0)
	for _, resp := range response {
		if len(resp) < 12 { continue }

		dateTime, _ := resp[0].(float64)
		open, _ := resp[1].(string)
		high, _ := resp[2].(string)
		low, _ := resp[3].(string)
		price, _ := resp[4].(string)
		vol, _ := resp[5].(string)

		datas = append(datas, &structs.SpiderKline{
			Exchange: 		k.slug,
			From: 			symbol.From,
			To: 			symbol.To,
			DateTime: 		int64(dateTime / 1000),
			Open: 			open,
			High: 			high,
			Low: 			low,
			Close: 			price,
			Volume: 		vol,
		})
	}
	return datas, nil
}
